package javase.ch02.sync.synchronizedandlock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @Desc TODO
 * @Author chenmin
 * @Date 2025/10/30
 *
 *  synchronized 非公平锁；
 *  Lock锁   可公平锁也可非公平锁（构造方法传入true/false）
 *
 *  public ReentrantLock() {
 *     sync = new NonfairSync();  //非公平锁
 *  }
 *
 *  public ReentrantLock(boolean fair) {
 *    sync = fair ? new FairSync() : new NonfairSync();  //true则是公平锁  false则是非公平锁
 *  }
 *
 *  公平锁： 按照等待获取锁的线程，它的等待时间进行获取，等待时间长的具有优先获取锁的权利
 *
 *  公平锁
 *     1.ReentrantLock 构造参数传入true 得到一个公平锁
 *     2.FairSync
 *     3.通过hasQueuedPredecessors()方法，判断同步队列中是否有先驱节点；若没有先驱节点的存在则可以获取锁
 *
 *  非公平锁
 *     1.synchronized是非公平锁 ， ReentrantLock默认使用的也是非公平锁，构造参数传入false也是非公平锁
 *     2.NonfairSync
 *     3.先占先得，只要能够抢占到同步状态
 *     4.最大缺点：容易出现锁饥饿现象
 *
 */
public class FairSyncDemo {

    public static void main(String[] args) {
        //共同资源
        Ticket ticket = new Ticket();

        new Thread(()-> {
            for (int i = 0; i < 35; i++) {
                ticket.sale();
            }
        } , "A窗口").start();

        new Thread(()-> {
            for (int i = 0; i < 35; i++) {
                ticket.sale();
            }
        } , "B窗口").start();

        new Thread(()-> {
            for (int i = 0; i < 35; i++) {
                ticket.sale();
            }
        } , "C窗口").start();

        new Thread(()-> {
            for (int i = 0; i < 35; i++) {
                ticket.sale();
            }
        } , "D窗口").start();
    }

}
class Ticket{
    private int num = 30;

    //非公平锁false   公平锁true
    private final ReentrantLock lock = new ReentrantLock(true);


    //1.不要卖出同一张票  2.不能卖出负数的票号
    public void sale(){
        //获取锁
        lock.lock();
        try{
            if(num>0){
                System.out.println(Thread.currentThread().getName()+"卖了一张票 ， 票号："+(num--) + "，目前还剩下"+num+"票");
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }
    }
}
